JBoss Community Archive (Read Only)

GateIn Portal 3.9

GateIn Module Definition (GMD)

Declaring a module

We will first explain how a module can be integrated and consume dependencies, i.e. other modules. A GateIn module consists of a JavaScript self-executing function and its declaration in the gatein-resources.xml descriptor of the web application. The descriptor defines the module and its dependencies. At runtime, GateIn Portal builds a graph of resouces and their dependencies. When a client requests a particular module it will invoke a JS function that call RequireJS to resolve dependencies.

For instance if we have a foo module that uses the jQuery dependency:

foo.js
(function ($) {
  // Do something with jQuery
})(jQuery)

Our module is declared as a self-executing function in the foo.js file. This file is then declared in the gatein-resources.xml file:

gatein-resources.xml
...
<module>
  <name>foo</name>
  <script>
    <path>/foo.js</path>
  </script>
  <depends>
    <module>jquery</module>
    <as>jQuery</as>
  </depends>
</module>
...

The self-executing function declares

  • parameter for the function: $

  • arguments of the function invocation: jQuery

The self-executing function argument must match the dependencies

  • Function do no need to match XML dependencies order

  • Function can use parameter subset: an dependency can be declared in XML but not consumed as an argument

  • Parameters must be aliased in dependencies with the <as> tag XML

The self executing function argument is a JavaScript construct. The purpose of this construct is to pass arguments to the function and let the function name the arguments like they want and override the current scope of execution. For example jQuery uses it:

(function(window, undefined) { .... })(window);

Resources are related by the concept of dependency relationship that specifies how scripts are related to each other and how the modular system should be honored. In our example, the foo module needs to use jQuery, we say that they are in relationship: the module foo depends on jQuery. When the module is loaded, the jQuery module must be available to the module.

Translation to the AMD system

GateIn Portal will wrap the above JavaScript code into an AMD module:

define("SHARED/foo", ["SHARED/jquery"], function(jQuery) {
  return (function($) {
    // Do something with jQuery
  })(jQuery);
});
  • logical identifiers are translated to AMD identifiers

    • the foo module is translated to the SHARED/foo AMD module identifier, the SHARED prefix is added by GateIn for scoping the name, there are other existing scopes such as PORTLET and PORTAL

    • the dependency on the jquery module is translated to a ["SHARED/jquery"] AMD module dependency

  • the module function is wrapped two times

    • a first time by the GateIn module wrapper that delegates to the module function, the goal of this function is to provide a lazy evaluation of the module self-executing function.

    • a second time by the define AMD function that takes care of loading the module properly

  • the self-executing function module arguments must match the module dependencies expressed in the XML declaration

    • the jquery dependency is aliased to the jQuery name thanks to the XML as tag, as a consequence the GateIn function wrapper parameter is named jQuery

    • the module self-executing function argument is named jQuery to match the declared alias

    • the module self-executing function parameter is named $ and thus redefines the jquery depenendency to $ locally

At runtime the following happens:

  • the define function is invoked and declares the dependency

  • when the dependency is resolved (i.e the jquery module is loaded and available)

    • the module wrapper is invoked with the jQuery argument containing the jquery dependency

    • the module wrapper evaluates the self-executing function that resolves the jQuery argument to the jquery dependency

    • the self-executing function is invoked and the jquery dependency is available under the name $

Producing dependencies

In our example we have seen that a module is able to consume dependencies as arguments, now we need to explain how a module can produce a dependency. When a module self-executing function is evaluated it can return an object, this precise object is what the module itself. Let's modify our previous example to return a value:

foo.js
(function ($) {
  // Do something with jQuery
  return {hello:"world"}
})($)

In this example we return a simple JavaScript object, this object will be stored by the dependency system of AMD and provided as arguments of modules that want to consume the foo module. Pretty simple isn't it ?

Portlet dynamic module

As seen previous, portlet dependencies can be expressed in the gatein-resources.xml file, it forces to declare the portlet dependencies at packaging time when the corresponding war file is created.

The JSR286 specification provides a mechanism for modifying portal headers that can be used to load JavaScript files. Although this mechanism is portable, it has severe drawbacks:

  • A script can be loaded multiple times, specially if two portlets in two different war files load the same scripts since the only way to identify a script is by its URL

  • Scripts have to be loaded by the head section of the portal impacting front end performances

GateIn allows to provide the best of both worlds and create dynamic dependencies of a portlet at runtime, when the render phase of the portlet occurs:

public void render(RenderRequest req, RenderResponse resp) throws PortletException, IOException {
  resp.setProperty("org.gatein.javascript.dependency", "base");
  resp.addProperty("org.gatein.javascript.dependency", "common");
}

This code is equivalent to the following declaration:

<portlet>
  <name>MyPortlet</name>
  <module>
    <depends>
      <module>base</module>
    </depends>
    <depends>
      <module>common</module>
    </depends>
  </module>
</portlet>

Aliases

When a module is defined, the module name will be used in a JavaScript self-executing function argument:

<module>
  <name>foo</name>
  ...
</module>
<module>
  <name>bar</name>
  ...
  <depends>
    <module>foo</module>
  </depends>
</module>

The corresponding module foo code is:

(function(foo) {
})(foo)

Aliases allow to change this name and provide a different name for arguments. Aliasing is done thanks to the as XML tag:

Module alias

Other modules that depends on this will refer to it by the module alias defined in gatein-resources.xml.

<module>
  <name>foo</name>
  <as>Foo</as>
  ...
</module>
<module>
  <name>bar</name>
  ...
  <depends>
    <module>foo</module>
  </depends>
</module>

The corresponding module foo code is:

(function(Foo) {
})(Foo)

Dependency alias

The same as tag can be used in the depends tags providing a local alias:

<module>
  <name>foo</name>
  ...
</module>
<module>
  <name>bar</name>
  ...
  <depends>
    <module>foo</module>
    <as>Foo</as>
  </depends>
</module>
JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-10 13:30:49 UTC, last content change 2014-04-15 07:24:08 UTC.